/*************************************************************************************
 * Nombre del archivo: Cola_SJF.java
 * Universidad del Valle de Guatemala
 * Curso: Sistemas Operativos
 * @author martin
 *          Martín Guzmán 08041
 * Fecha: Febrero de 2010
 * Descripción:
*************************************************************************************/
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;

public class Cola_SJF extends Cola_Abstracta<Proceso>{

    public Cola_SJF(){}

    /***********************************************
     * Método: get
     * Uso: obtiene el elemento especificado
     * @return G con el elemento de la cola...
    ***********************************************/
    public Proceso get(int i){
        return this.lista.get(i);
    }

    /***********************************************
     * Método: add
     * Uso: agrega un nuevo elemento a la cola
     * @return void agrega al final de la cola
    ***********************************************/
    public void add(Proceso nuevo){
        nuevo.cola_en_la_que_esta=this.numero_cola;
        this.lista.add(nuevo);//agrega el elemento
        Proceso temp_primero = this.lista.getFirst();//toma el primero en la lista para revisar el preemptive
        this.ultimo_entrante=nuevo;//referencia al último elemento entrante
        //ordena la lista según la ecuación
        Collections.sort(this.lista, new Comparator<Proceso>() {
            public int compare(Proceso o1, Proceso o2) {
                Integer a1 = ec_sjf(o1);
                Integer a2 = ec_sjf(o2);
                return a1-a2;
            }
        });
        //si no era preemptive tiene que volver a estar hasta adelante el proceso que iba primero...
        if(!this.preemptive && this.lista.size()!=1){
            this.lista.remove(temp_primero);
            this.lista.addFirst(temp_primero);
        }

        this.ultimo_entrante.setQuantum_restante(this.quantum);
        this.ultimo_entrante.setEstado(2);//para poner en estado ready
        this.ultimo_entrante.cola_en_la_que_esta=this.getNumero_cola();
        this.ultimo_entrante.io_waiting=false;

        //System.out.println(this.lista);

    }

    private int ec_sjf(Proceso proc){

        //cosas a ponderar:
            //cantidad de instrucciones
            //cantidad de ciclos (jmps o etiquetas)
            //cantidad de IO

        int cant_instrucciones = proc.instrucciones.size();
        int cant_ciclos = proc.Tabla_simbolos.size();
        int cant_IO = 0;
        for(int i=0;i<proc.instrucciones.size();i++){
            String cad = proc.instrucciones.get(i).split(" ")[0].toLowerCase();
            if(proc.System_calls.containsKey(cad)){
                cant_IO++;
            }
        }
        //System.out.println("Proceso"+proc.toString()+"cantidad de IO:"+cant_IO);
        int ecuacion = (int) (cant_instrucciones*4 + Math.pow(2, cant_ciclos)+Math.sqrt((double)cant_IO));
        return ecuacion;
    }

    /***********************************************
     * Método: getLast_in
     * Uso: obtiene el último elemento que entró a la cola
     * @return G con el último objeto que entró a la cola
    ***********************************************/
    public Proceso getLast_in() {
        return this.ultimo_entrante;
    }
}
